package com.bigknow.appstore.proxy.service;

import com.bigknow.appstore.proxy.cache.impl.EhCacheManager;
import com.bigknow.appstore.proxy.db.impl.MongodbHelper;
import com.bigknow.appstore.proxy.entity.ProxyMeta;
import com.bigknow.appstore.proxy.enumerate.ProxyState;
import com.bigknow.appstore.proxy.exceptions.processor.impl.ErrorProcessor;
import com.bigknow.appstore.proxy.log.ILogWriter;
import com.bigknow.appstore.proxy.log.impl.BatchMergeMongoDBWriter;
import com.bigknow.appstore.proxy.log.impl.MongoDBWriter;
import com.bigknow.appstore.proxy.server.IProxyServer;
import com.bigknow.appstore.proxy.server.impl.HttpProxyServer;
import org.mongodb.morphia.Datastore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by chaos on 2016/9/30.
 */
@Service
public class ProxyManager {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${app.server.ip}")
    private String ip;
    @Value("${app.server.port}")
    private String port;

    @Autowired
    private Datastore datastore;

    @Autowired
    private EhCacheManager cacheManager;

    private Map<String, IProxyServer> proxyServerMap = new ConcurrentHashMap<>();

    /**
     * http为 9000
     * https为9100
     */
    @PostConstruct
    public void init() {
        while (!cacheManager.isRun()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        for (ProxyMeta proxyMeta : datastore.find(ProxyMeta.class).asList()) {
            ILogWriter logWriter = new MongoDBWriter(datastore);
            //修改为批量日志合并writer
            BatchMergeMongoDBWriter writer = new BatchMergeMongoDBWriter(logWriter);

            HttpProxyServer server = new HttpProxyServer(proxyMeta, cacheManager, writer
                    , new ErrorProcessor(writer), new MongodbHelper(datastore));

/*            ShowRequestInfoDebugHandler in = new ShowRequestInfoDebugHandler(server, cacheManager, logWriter);
            server.addCustomInboundHandler(in);
            ShowResponseHeaderDebugHandler out = new ShowResponseHeaderDebugHandler(server, cacheManager, logWriter);
            server.addCustomOutboundHandler(out);*/
            server.setRealServerIp(ip);
            server.setRealAppSysPort(port);
            server.startProxy();
            proxyServerMap.put(server.getProxyId(), server);
        }
    }

    /**
     * 启动proxyServer
     *
     * @param proxyMeta
     */
    public void startProxyServer(ProxyMeta proxyMeta) {
        if (proxyServerMap.containsKey(proxyMeta.getId())) {
            //如果已经是启动状态调用此方法是不会重复启动的
            proxyServerMap.get(proxyMeta.getId()).startProxy();
        } else {
            ILogWriter logWriter = new MongoDBWriter(datastore);
            HttpProxyServer server = new HttpProxyServer(proxyMeta, cacheManager, logWriter
                    , new ErrorProcessor(logWriter), new MongodbHelper(datastore));
            server.startProxy();
            proxyServerMap.put(server.getProxyId(), server);
        }
    }

    /**
     * 停止proxyServer
     * @param proxyId
     */
    public void stopProxyServer(String proxyId) {
        if (proxyServerMap.containsKey(proxyId)) {
            IProxyServer proxyServer = proxyServerMap.get(proxyId);
            if (!proxyServer.getState().equals(ProxyState.STOP)) {
                proxyServer.stopProxy();
            }
        }
    }

    /**
     * 获取ProxyServer状态
     * @param proxyId
     */
    public ProxyState getProxyServerState(String proxyId){
        if (proxyServerMap.containsKey(proxyId)) {
            return proxyServerMap.get(proxyId).getState();
        }else{
            throw new RuntimeException("no proxy server id is: "+proxyId);
        }
    }

    @PreDestroy
    public void shutdown(){
        logger.info("shut down http proxy server");
        List<ProxyMeta> list =  findAllProxyMeta();
        for (ProxyMeta proxyMeta : list) {
            logger.info("stop ProxyServer id is :"+ proxyMeta.getId());
            stopProxyServer(proxyMeta.getId());
        }
    }

    /**
     * 获取所有的Proxymeta
     * @return
     */
    public List<ProxyMeta> findAllProxyMeta(){
        return datastore.find(ProxyMeta.class).asList();
    }

}
